const memoize = require("./template.js")

function testMemoize() {
  console.log(
    "1. 基本缓存功能:",
    (() => {
      let callCount = 0
      const fn = (a, b) => {
        callCount++
        return a + b
      }
      const memoizedFn = memoize(fn)

      const result1 = memoizedFn(2, 3)
      const result2 = memoizedFn(2, 3)

      return result1 === 5 && result2 === 5 && callCount === 1
    })()
  )

  console.log(
    "2. 不同参数会调用:",
    (() => {
      let callCount = 0
      const fn = (a, b) => {
        callCount++
        return a + b
      }
      const memoizedFn = memoize(fn)

      memoizedFn(1, 2)
      memoizedFn(2, 3)
      memoizedFn(1, 2) // 应该从缓存返回

      return callCount === 2
    })()
  )

  console.log(
    "3. 单参数函数:",
    (() => {
      let callCount = 0
      const fn = (x) => {
        callCount++
        return x * x
      }
      const memoizedFn = memoize(fn)

      const result1 = memoizedFn(5)
      const result2 = memoizedFn(5)
      const result3 = memoizedFn(3)

      return (
        result1 === 25 && result2 === 25 && result3 === 9 && callCount === 2
      )
    })()
  )

  console.log(
    "4. 无参数函数:",
    (() => {
      let callCount = 0
      const fn = () => {
        callCount++
        return Math.random()
      }
      const memoizedFn = memoize(fn)

      const result1 = memoizedFn()
      const result2 = memoizedFn()

      return result1 === result2 && callCount === 1
    })()
  )

  console.log(
    "5. 字符串参数:",
    (() => {
      let callCount = 0
      const fn = (str) => {
        callCount++
        return str.toUpperCase()
      }
      const memoizedFn = memoize(fn)

      memoizedFn("hello")
      memoizedFn("hello")
      memoizedFn("world")

      return callCount === 2
    })()
  )

  console.log(
    "6. 复杂计算缓存:",
    (() => {
      let callCount = 0
      const fibonacci = (n) => {
        callCount++
        if (n <= 1) return n
        return n * (n - 1) // 简化版本
      }
      const memoizedFib = memoize(fibonacci)

      memoizedFib(5)
      memoizedFib(5)
      memoizedFib(3)
      memoizedFib(5) // 应该从缓存返回

      return callCount === 2
    })()
  )

  console.log(
    "7. 多参数顺序敏感:",
    (() => {
      let callCount = 0
      const fn = (a, b, c) => {
        callCount++
        return a + b + c
      }
      const memoizedFn = memoize(fn)

      memoizedFn(1, 2, 3)
      memoizedFn(3, 2, 1) // 不同顺序，应该调用
      memoizedFn(1, 2, 3) // 相同参数，应该缓存

      return callCount === 2
    })()
  )

  console.log(
    "8. 返回值类型保持:",
    (() => {
      const fn = (x) => ({ result: x * 2 })
      const memoizedFn = memoize(fn)

      const result1 = memoizedFn(5)
      const result2 = memoizedFn(5)

      return (
        result1 === result2 && // 应该返回相同的对象引用
        result1.result === 10
      )
    })()
  )

  console.log(
    "9. null和undefined参数:",
    (() => {
      let callCount = 0
      const fn = (a, b) => {
        callCount++
        return `${a}-${b}`
      }
      const memoizedFn = memoize(fn)

      memoizedFn(null, undefined)
      memoizedFn(null, undefined)
      memoizedFn(undefined, null)

      return callCount === 2
    })()
  )

  console.log(
    "11. 函数作为参数:",
    (() => {
      let callCount = 0
      const fn = (func, x) => {
        callCount++
        return func(x)
      }
      const memoizedFn = memoize(fn)

      const addOne = (x) => x + 1

      memoizedFn(addOne, 5)
      memoizedFn(addOne, 5) // 相同函数和参数

      return callCount === 1
    })()
  )

  console.log(
    "12. 布尔值参数:",
    (() => {
      let callCount = 0
      const fn = (flag) => {
        callCount++
        return flag ? "true" : "false"
      }
      const memoizedFn = memoize(fn)

      memoizedFn(true)
      memoizedFn(true)
      memoizedFn(false)
      memoizedFn(true) // 应该从缓存返回

      return callCount === 2
    })()
  )

  console.log(
    "13. 大量参数:",
    (() => {
      let callCount = 0
      const fn = (...args) => {
        callCount++
        return args.reduce((a, b) => a + b, 0)
      }
      const memoizedFn = memoize(fn)

      memoizedFn(1, 2, 3, 4, 5)
      memoizedFn(1, 2, 3, 4, 5)

      return callCount === 1
    })()
  )

  console.log(
    "14. 异常处理缓存:",
    (() => {
      let callCount = 0
      const fn = (x) => {
        callCount++
        if (x < 0) throw new Error("Negative number")
        return x * 2
      }
      const memoizedFn = memoize(fn)

      try {
        memoizedFn(-1)
      } catch (e) {}

      try {
        memoizedFn(-1) // 相同参数，可能缓存异常
      } catch (e) {}

      // 异常是否缓存取决于实现，这里只验证不会崩溃
      return callCount >= 1
    })()
  )

  console.log(
    "15. this上下文保持:",
    (() => {
      let callCount = 0
      const obj = {
        value: 10,
        multiply: function (x) {
          callCount++
          return this.value * x
        }
      }

      const memoizedMultiply = memoize(obj.multiply.bind(obj))

      const result1 = memoizedMultiply(5)
      const result2 = memoizedMultiply(5)

      return result1 === 50 && result2 === 50 && callCount === 1
    })()
  )

  console.log(
    "16. 原函数不变:",
    (() => {
      let originalCallCount = 0
      let memoizedCallCount = 0

      const originalFn = (x) => {
        originalCallCount++
        return x * 2
      }

      const memoizedFn = memoize((x) => {
        memoizedCallCount++
        return x * 2
      })

      originalFn(5)
      originalFn(5)
      memoizedFn(5)
      memoizedFn(5)

      return originalCallCount === 2 && memoizedCallCount === 1
    })()
  )

  console.log(
    "17. 性能提升验证:",
    (() => {
      let expensiveCallCount = 0
      const expensiveFunction = (n) => {
        expensiveCallCount++
        let result = 0
        for (let i = 0; i < n; i++) {
          result += i
        }
        return result
      }

      const memoizedFn = memoize(expensiveFunction)

      memoizedFn(1000)
      memoizedFn(1000)
      memoizedFn(1000)

      return expensiveCallCount === 1
    })()
  )
}

testMemoize()
